🎖️GitЯра🎖️
.github/workflows/pull-request-target.yml chore/develocity-tuning (359761e6) Text, 5.60 KB
Tff7b72nameTb4b4b4: Ta5d6ff"Ta5d6ffPullTe6edf3 Ta5d6ffRequestTe6edf3 Ta5d6ffLabelerTa5d6ff"
Tff7b72onTb4b4b4:
Tff7b72pull_request_targetTb4b4b4:
Tff7b72typesTb4b4b4: Tb4b4b4[Te6edf3openedTb4b4b4, Te6edf3synchronizeTb4b4b4, Te6edf3reopenedTb4b4b4, Te6edf3labeledTb4b4b4, Te6edf3unlabeledTb4b4b4]
T8b949e# Do not execute arbitrary code on this workflow.
T8b949e# See warnings at https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows#pull_request_target
Tff7b72concurrencyTb4b4b4:
Tff7b72groupTb4b4b4: Ta5d6ff${{Ta5d6ff Ta5d6ffgithub.workflowTa5d6ff Ta5d6ff}}-${{Ta5d6ff Ta5d6ffgithub.event.pull_request.numberTa5d6ff Ta5d6ff}}
Tff7b72cancel-in-progressTb4b4b4: Ta5d6fftrue
Tff7b72jobsTb4b4b4:
Tff7b72labelerTb4b4b4:
Tff7b72permissionsTb4b4b4:
Tff7b72contentsTb4b4b4: Ta5d6ffread
Tff7b72pull-requestsTb4b4b4: Ta5d6ffwrite
Tff7b72runs-onTb4b4b4: Ta5d6ffubuntu-24.04-arm
Tff7b72timeout-minutesTb4b4b4: Ta5d6ff5
Tff7b72stepsTb4b4b4:
Tb4b4b4- Tff7b72nameTb4b4b4: Ta5d6ffAuto-labelTa5d6ff Ta5d6ffPR
Tff7b72usesTb4b4b4: Ta5d6ffactions/github-script@v9
Tff7b72withTb4b4b4:
Tff7b72scriptTb4b4b4: Tb4b4b4|
Tff7b72const branch = context.payload.pull_request.head.ref;
Tff7b72const title = context.payload.pull_request.title || '';
Tff7b72const labels = new Set();
Tff7b72// Match branch prefix (e.g. feat/..., fix/..., chore-something)
Tff7b72// Also parse conventional-commit-style PR titles as a fallback: type(scope): subject
Tff7b72const branchPrefix = branch.split(/[\/\-_]/)[0].toLowerCase();
Tff7b72const titleMatch = title.match(/^(\w+)(?:\(([^)]+)\))?:/);
Tff7b72const titlePrefix = titleMatch?.[1]?.toLowerCase();
Tff7b72const titleScope = titleMatch?.[2]?.toLowerCase();
Tff7b72// Map prefixes to changelog-aligned labels
Tff7b72const prefixMap = {
Tff7b72'feat': 'enhancement',
Tff7b72'feature': 'enhancement',
Tff7b72'fix': 'bugfix',
Tff7b72'bug': 'bugfix',
Tff7b72'bugfix': 'bugfix',
Tff7b72'hotfix': 'bugfix',
Tff7b72'refactor': 'refactor',
Tff7b72'chore': 'chore',
Tff7b72'build': 'build',
Tff7b72'ci': 'ci',
Tff7b72'test': 'testing',
Tff7b72'tests': 'testing',
Tff7b72'docs': 'documentation',
Tff7b72'doc': 'documentation',
Tff7b72'perf': 'enhancement',
Tff7b72'style': 'refactor',
Tff7b72'repo': 'repo',
Tff7b72'release': 'release',
Tff7b72};
Tff7b72// Map conventional-commit scopes to labels not derivable from the type alone
Tff7b72const scopeMap = {
Tff7b72'desktop': 'desktop',
Tff7b72};
Tff7b72// Label from branch prefix
Tff7b72if (prefixMap[branchPrefix]) labels.add(prefixMap[branchPrefix]);
Tff7b72// Label from PR title prefix (if different from branch)
Tff7b72if (titlePrefix && prefixMap[titlePrefix] && !labels.has(prefixMap[titlePrefix])) {
Tff7b72labels.add(prefixMap[titlePrefix]);
Tff7b72}
Tff7b72// Label from PR title scope, e.g. "feat(desktop): ..."
Tff7b72if (titleScope && scopeMap[titleScope]) labels.add(scopeMap[titleScope]);
Tff7b72// Path-based labels from changed files
Tff7b72const pathLabels = [
Tff7b72{ prefix: '.github/', label: 'repo' },
Tff7b72{ prefix: 'build-logic/', label: 'build' },
Tff7b72{ prefix: 'desktopApp/', label: 'desktop' },
Tff7b72].filter(({ label }) => !labels.has(label));
Tff7b72if (pathLabels.length > 0) {
Tff7b72try {
Tff7b72const files = await github.paginate(
Tff7b72github.rest.pulls.listFiles,
Tff7b72{ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.payload.pull_request.number, per_page: 100 },
Tff7b72(res) => res.data.map(f => f.filename)
Tff7b72);
Tff7b72for (const { prefix, label } of pathLabels) {
Tff7b72if (files.some(f => f.startsWith(prefix))) labels.add(label);
Tff7b72}
Tff7b72} catch (e) {
Tff7b72core.warning(`Could not list PR files (rate limited?): ${e.message}`);
Tff7b72}
Tff7b72}
Tff7b72if (labels.size > 0) {
Tff7b72const labelArray = [...labels];
Tff7b72core.info(`Applying labels: ${labelArray.join(', ')}`);
Tff7b72try {
Tff7b72await github.rest.issues.addLabels({
Tff7b72owner: context.repo.owner,
Tff7b72repo: context.repo.repo,
Tff7b72issue_number: context.payload.pull_request.number,
Tff7b72labels: labelArray,
Tff7b72});
Tff7b72} catch (e) {
Tff7b72core.warning(`Could not apply labels (rate limited?): ${e.message}`);
Tff7b72}
Tff7b72} else {
Tff7b72core.info('No labels matched for this PR.');
Tff7b72}
Tff7b72// Enforce that the PR ends up with a required label. Done here (not in a
Tff7b72// separate pull_request workflow) so the check sees labels this job just
Tff7b72// applied: label events fired by GITHUB_TOKEN don't re-trigger workflows,
Tff7b72// so a separate checker would read an empty label set at `opened` and stay
Tff7b72// red forever. Bot PRs are labeled by their own flows and are skipped.
Tff7b72const author = context.payload.pull_request.user.login;
Tff7b72const headRef = context.payload.pull_request.head.ref;
Tff7b72const skipAuthors = ['renovate[bot]', 'github-actions[bot]', 'dependabot[bot]'];
Tff7b72const skipRefs = ['scheduled-updates', 'l10n_main'];
Tff7b72if (!skipAuthors.includes(author) && !skipRefs.includes(headRef)) {
Tff7b72const requiredLabels = ['bugfix', 'enhancement', 'automation', 'dependencies', 'repo', 'release', 'refactor', 'desktop', 'chore', 'ci', 'build', 'testing', 'documentation'];
Tff7b72const effectiveLabels = new Set([
Tff7b72...context.payload.pull_request.labels.map(l => l.name),
Tff7b72...labels,
Tff7b72]);
Tff7b72if (!requiredLabels.some(l => effectiveLabels.has(l))) {
Tff7b72core.setFailed(`PR must have at least one of the following labels before it can be merged: ${requiredLabels.join(', ')}.`);
Tff7b72}
Tff7b72}
Served by rngit 1.5.1 - Generated in 0.05s